/**
 * @file bsp_eflash.c
 * @brief 
 * @author  ()
 * @version 1.0
 * @date 2024-09-13
 * 
 * @copyright Copyright (C) 2019 Queclink Wireless Solutions (ShenZhen) Co., Ltd. All Rights Reserved.
 * 
 * @par 修改日志:
 * <table>
 * <tr><th>Date       <th>Version <th>Author  <th>Description
 * <tr><td>2024-09-13 <td>1.0     <td>     <td>内容
 * </table>
 */

/* includes ---------------------------------------------------------------------------------------------------------*/
#include "bsp_eflash.h"
#include "bsp_xspi.h"
#include "hal_adapter.h"
#include "public/errno.h"

#include "global.h"

SPI_HandleTypeDef eflash_spi_ctx;


/**
 * @brief 外挂flash硬件初始化
 * @return int32_t 
 */
int32_t bsp_eflash_init(void)
{
    GPIO_InitTypeDef GPIO_InitStruct = {0};

    bsp_eflash_clock_enable();

    /* nor flash power control, high availd */
    GPIO_InitStruct.Pin = EXT_FLASH_POWER_PIN;
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    HAL_GPIO_Init(EXT_FLASH_POWER_PORT, &GPIO_InitStruct);
    

    // 外部flash poweron
    bsp_eflash_poweron();

#if defined(STM32H563xx)
    return bsp_xspi_init();
#elif defined(STM32U575xx)
    RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0};

    /** Initializes the peripherals clock
     */
    PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_SPI1;
    PeriphClkInitStruct.Spi1ClockSelection = RCC_SPI1CLKSOURCE_PCLK2;
    if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
    {
        Error_Handler();
    }

        /* Peripheral clock enable */
    __HAL_RCC_SPI1_CLK_ENABLE();
    __HAL_RCC_GPIOA_CLK_ENABLE();
    __HAL_RCC_GPIOB_CLK_ENABLE();
    /*******************************************
     * PB3	SPI3_SCK	FLASH_SCLK
     * PB4	SPI3_MISO	FLASH_MISO
     * PB5	SPI3_MOSI	FLASH_MOSI
     * PA151	SPI3_NSS FLASH NSS低有效
     * PC8	OUTPUT	G_SENSOR 电源控制，0-打开电源;1-关闭电源
     ********************************************/
    GPIO_InitStruct.Pin = GPIO_PIN_15;
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    GPIO_InitStruct.Alternate = GPIO_AF5_SPI1;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

    GPIO_InitStruct.Pin = GPIO_PIN_3;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_PULLUP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    GPIO_InitStruct.Alternate = GPIO_AF5_SPI1;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

    GPIO_InitStruct.Pin = GPIO_PIN_4;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_PULLUP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    GPIO_InitStruct.Alternate = GPIO_AF5_SPI1;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

    GPIO_InitStruct.Pin = GPIO_PIN_5;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    GPIO_InitStruct.Alternate = GPIO_AF5_SPI1;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

    eflash_spi_ctx.Instance = EFLASH_SPI_PERIHERAL;
    eflash_spi_ctx.Init.Mode = SPI_MODE_MASTER;
    eflash_spi_ctx.Init.Direction = SPI_DIRECTION_2LINES;
    eflash_spi_ctx.Init.DataSize = SPI_DATASIZE_8BIT;
    eflash_spi_ctx.Init.CLKPolarity = SPI_POLARITY_HIGH;
    eflash_spi_ctx.Init.CLKPhase = SPI_PHASE_2EDGE;
    eflash_spi_ctx.Init.NSS = SPI_NSS_SOFT;
    eflash_spi_ctx.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2;
    eflash_spi_ctx.Init.FirstBit = SPI_FIRSTBIT_MSB;
    eflash_spi_ctx.Init.TIMode = SPI_TIMODE_DISABLE;
    eflash_spi_ctx.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
    eflash_spi_ctx.Init.CRCPolynomial = 0x7;
    eflash_spi_ctx.Init.NSSPMode = SPI_NSS_PULSE_DISABLE;
    eflash_spi_ctx.Init.NSSPolarity = SPI_NSS_POLARITY_LOW;
    eflash_spi_ctx.Init.FifoThreshold = SPI_FIFO_THRESHOLD_01DATA;
    eflash_spi_ctx.Init.MasterSSIdleness = SPI_MASTER_SS_IDLENESS_01CYCLE;
    eflash_spi_ctx.Init.MasterInterDataIdleness = SPI_MASTER_INTERDATA_IDLENESS_01CYCLE;
    eflash_spi_ctx.Init.MasterReceiverAutoSusp = SPI_MASTER_RX_AUTOSUSP_ENABLE;
    eflash_spi_ctx.Init.MasterKeepIOState = SPI_MASTER_KEEP_IO_STATE_DISABLE;
    eflash_spi_ctx.Init.IOSwap = SPI_IO_SWAP_DISABLE;
    eflash_spi_ctx.Init.ReadyMasterManagement = SPI_RDY_MASTER_MANAGEMENT_INTERNALLY;
    eflash_spi_ctx.Init.ReadyPolarity = SPI_RDY_POLARITY_HIGH;  
    if (HAL_SPI_Init(&eflash_spi_ctx) != HAL_OK)
    {
        Error_Handler();
    }

    /* SPI1 interrupt Init */
    // HAL_NVIC_SetPriority(SPI1_IRQn, 0, 0);
    // HAL_NVIC_EnableIRQ(SPI1_IRQn);

    return 0;
#endif
}

/// @brief 外部flash去初始化
/// @param  
void bsp_eflash_deinit(void)
{
    
}


/// @brief flash使能
/// @param  
/// @return 
int32_t bsp_eflash_enable(void)
{
#if defined(STM32H563xx)
    return bsp_xspi_enable();
#elif defined(STM32U575xx)
    // nss set to low
    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_15, GPIO_PIN_RESET);
    return 0;
#endif    
}

/// @brief flash失能
/// @param  
/// @return 
int32_t bsp_eflash_disable(void)
{
    int32_t res = 0;

#if defined(STM32H563xx)
    res = bsp_xspi_disable();
#elif defined(STM32U575xx)
    // nss set to high
    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_15, GPIO_PIN_SET);
#endif
    return res;
}

/// @brief flash spi写
/// @param buf 
/// @param cnt 
/// @return 
ssize_t bsp_eflash_write(const void *buf, size_t cnt)
{
#if defined(STM32H563xx)
    if ((cnt = bsp_xspi_write((void *)buf, cnt)) < 0)
        return -EIO;
#elif defined(STM32U575xx)
    if((cnt = HAL_SPI_Transmit(&eflash_spi_ctx, buf, cnt, 1000)) < 0)
        return -EIO;
#endif
    return cnt;
}

bool bsp_eflash_get_power_status(void)
{
    return (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_15) == GPIO_PIN_RESET);
}

/// @brief flash spi读
/// @param buf 
/// @param cnt 
/// @return 
ssize_t bsp_eflash_read(void *buf, size_t cnt)
{
#if defined(STM32H563xx)
    if ((cnt = bsp_xspi_read((void *)buf, cnt)) < 0)
        return -EIO;
#elif defined(STM32U575xx)
    if((cnt = HAL_SPI_Receive(&eflash_spi_ctx, buf, cnt, 1000)) < 0)
        return -EIO;
#endif        
    return cnt;
}


/**
 * @brief 中断处理函数
 */
void eflash_irq_handler(void)
{
    HAL_SPI_IRQHandler(&eflash_spi_ctx);
}

/**
 * @brief flash 休眠处理函数
 */
void bsp_flash_sleep(void)
{
    GPIO_InitTypeDef GPIO_InitStruct = {0};

    HAL_GPIO_DeInit(GPIOA, GPIO_PIN_15);
    HAL_GPIO_DeInit(GPIOB, GPIO_PIN_3|GPIO_PIN_4|GPIO_PIN_5);
    HAL_GPIO_DeInit(EXT_FLASH_POWER_PORT, EXT_FLASH_POWER_PIN);

    GPIO_InitStruct.Pin = GPIO_PIN_15;
    GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

    GPIO_InitStruct.Pin = GPIO_PIN_3|GPIO_PIN_4|GPIO_PIN_5;
    GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

    GPIO_InitStruct.Pin = EXT_FLASH_POWER_PIN;
    GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    HAL_GPIO_Init(EXT_FLASH_POWER_PORT, &GPIO_InitStruct);
}

/**
 * @brief flash 唤醒处理函数
 */
void bsp_flash_wakeup(void)
{
    GPIO_InitTypeDef GPIO_InitStruct = {0};

    HAL_GPIO_DeInit(GPIOA, GPIO_PIN_15);
    HAL_GPIO_DeInit(GPIOB, GPIO_PIN_3|GPIO_PIN_4|GPIO_PIN_5);
    HAL_GPIO_DeInit(EXT_FLASH_POWER_PORT, EXT_FLASH_POWER_PIN);

    GPIO_InitStruct.Pin = GPIO_PIN_15;
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    GPIO_InitStruct.Alternate = GPIO_AF5_SPI1;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

    GPIO_InitStruct.Pin = GPIO_PIN_3|GPIO_PIN_4|GPIO_PIN_5;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_PULLUP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    GPIO_InitStruct.Alternate = GPIO_AF5_SPI1;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

    GPIO_InitStruct.Pin = EXT_FLASH_POWER_PIN;
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    HAL_GPIO_Init(EXT_FLASH_POWER_PORT, &GPIO_InitStruct);
}